/*
 * 
 *  This file is part of Sourceprojects.org Lycia Copyright 2010 noctarius
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 */
package org.sourceprojects.lycia;

import java.util.List;

import org.sourceprojects.lycia.annotations.Nullable;
import org.sourceprojects.lycia.exceptions.LyciaParsingException;
import org.sourceprojects.lycia.internal.platform.PlatformFactory;
import org.w3c.dom.Element;
import org.xml.sax.ContentHandler;

/**
 * Base interface for a configurator used to handle configuration for an actual
 * instance of {@link LyciaParser}.
 * 
 * @author noctarius
 * @since 1.9.1
 * 
 * @param <B>
 *            Type of ContextObject to use
 */
public interface LyciaConfigurator<B> {

	/**
	 * Adds a {@link TagDefinitionParser} implementation to the instance of
	 * XmlParser
	 * 
	 * @param definitionParser
	 *            TagDefinitionParser implementation to add
	 * @since 1.9.1
	 */
	void addTagDefinitionParser(TagDefinitionParser<B> definitionParser);

	/**
	 * Adds a annotated Pojo implementation to the instance of XmlParser
	 * 
	 * @param definitionParser
	 *            TagDefinitionParser implementation to add
	 * @since 1.9.1
	 */
	void addTagDefinitionParser(Object definitionParser);

	/**
	 * Adds a bunch of {@link TagDefinitionParser} implementations to the
	 * instance of XmlParser
	 * 
	 * @param definitionParsers
	 *            Array of TagDefinitionParser implementations to add
	 * @since 1.9.1
	 */
	void addTagDefinitionParsers(TagDefinitionParser<B>[] definitionParsers);

	/**
	 * Adds a bunch of annotated Pojo implementations to the instance of
	 * XmlParser
	 * 
	 * @param definitionParsers
	 *            Array of TagDefinitionParser implementations to add
	 * @since 1.9.1
	 */
	void addTagDefinitionParsers(Object[] definitionParsers);

	/**
	 * Removes a {@link TagDefinitionParser} implementation from the instance of
	 * XmlParser
	 * 
	 * @param definitionParser
	 *            TagDefinitionParser implementation to remove
	 * @since 1.9.1
	 */
	void removeTagDefinitionParser(TagDefinitionParser<B> definitionParser);

	/**
	 * Removes a annotated Pojo implementation from the instance of XmlParser
	 * 
	 * @param definitionParser
	 *            TagDefinitionParser implementation to remove
	 * @since 1.9.1
	 */
	void removeTagDefinitionParser(Object definitionParser);

	/**
	 * Removes a bunch of {@link TagDefinitionParser} implementations from the
	 * instance of XmlParser
	 * 
	 * @param definitionParsers
	 *            Array of TagDefinitionParser implementations to remove
	 * @since 1.9.1
	 */
	void removeTagDefinitionParsers(TagDefinitionParser<B>[] definitionParsers);

	/**
	 * Removes a bunch of annotated Pojo implementations from the instance of
	 * XmlParser
	 * 
	 * @param definitionParsers
	 *            Array of TagDefinitionParser implementations to remove
	 * @since 1.9.1
	 */
	void removeTagDefinitionParsers(Object[] definitionParsers);

	/**
	 * Finds a {@link TagDefinitionParser} by given {@link QualifiedName}
	 * 
	 * @param localElement
	 *            The element to find a TagDefinitionParser for
	 * @param element
	 *            The DOM element to evaluate
	 * @return A pre-registered TagDefinitionParser
	 * @since 1.9.1
	 */
	TagDefinitionParser<B> findTagDefinitionParser(QualifiedName localElement,
			Element element);

	/**
	 * Finds {@link TagDefinitionParser}s by given {@link QualifiedName}
	 * 
	 * @param localElement
	 *            The element to find a TagDefinitionParser for
	 * @param element
	 *            The DOM element to evaluate
	 * @return Pre-registered TagDefinitionParsers
	 * @since 1.9.1
	 */
	List<TagDefinitionParser<B>> findTagDefinitionParsers(
			QualifiedName localElement, Element element);

	/**
	 * Finds a {@link TagDefinitionParser} by given tagName
	 * 
	 * @param tagName
	 *            The tagName
	 * @param namespaceURI
	 *            The namespace of the given tagName
	 * @param element
	 *            The DOM element to evaluate
	 * @return A pre-registered TagDefinitionParser
	 * @since 1.9.1
	 */
	TagDefinitionParser<B> findTagDefinitionParser(String tagName,
			String namespaceURI, Element element);

	/**
	 * Finds {@link TagDefinitionParser}s by given tagName
	 * 
	 * @param tagName
	 *            The tagName
	 * @param namespaceURI
	 *            The namespace of the given tagName
	 * @param element
	 *            The DOM element to evaluate
	 * @return Pre-registered TagDefinitionParsers
	 * @since 1.9.1
	 */
	List<TagDefinitionParser<B>> findTagDefinitionParsers(String tagName,
			String namespaceURI, Element element);

	/**
	 * Gets the style of delegation generation
	 * 
	 * @return GenerationStrategy style
	 * @since 1.9.1
	 */
	GenerationStrategy getGenerationStrategy();

	/**
	 * Sets the style of delegation generation, standard if
	 * {@link GenerationStrategy#ReflectiveGeneration}
	 * 
	 * @param generationStrategy
	 *            Style of GenerationStrategy
	 * @since 1.9.1
	 */
	void setGenerationStrategy(GenerationStrategy generationStrategy);

	/**
	 * Returns the parent {@link LyciaConfigurator}
	 * 
	 * @return The parent XmlParserConfigurator or null if base
	 *         XmlParserConfigurator
	 * @since 1.9.1
	 */
	LyciaConfigurator<B> getParentXmlParserConfigurator();

	/**
	 * Sets the implementation of the {@link GeneratorFactory} interface to use
	 * for internal generation of {@link Delegate}s.
	 * 
	 * @param generatorFactory
	 *            Actual implementation of the GeneratorFactory interface
	 * @since 1.9.5
	 */
	void setGeneratorFactory(GeneratorFactory<B> generatorFactory);

	/**
	 * Gets the implementation of the {@link GeneratorFactory} interface to use
	 * for internal generation of {@link Delegate}s.
	 * 
	 * @return Actual implementation of the GeneratorFactory interface
	 * @since 1.9.5
	 */
	GeneratorFactory<B> getGeneratorFactory();

	/**
	 * Adds a SAX {@link ContentHandler} to the parsers handler chain
	 * 
	 * @param contentHandler
	 *            ContentHandler to add to the chain
	 * @since 1.9.7
	 */
	void addContentHandler(ContentHandler contentHandler);

	/**
	 * Removes a SAX {@link ContentHandler} from the parsers handler chain
	 * 
	 * @param contentHandler
	 *            ContentHandler to remove from the chain
	 * @since 1.9.7
	 */
	void removeContentHandler(ContentHandler contentHandler);

	/**
	 * Returns all registered {@link ContentHandler}s
	 * 
	 * @return List of all ContentHandlers
	 * @since 1.9.7
	 */
	List<ContentHandler> getContentHandlers();

	/**
	 * Returns the internal {@link PlatformFactory} implementation depending on
	 * running platform
	 * 
	 * @return Platform dependent implementation of PlatformFactory
	 * @since 1.9.8
	 */
	PlatformFactory<B> getPlatformFactory();

	/**
	 * Sets if the parameter matcher should work in an null aware way. In this
	 * method matching behaviour no null parameters are allowed. If a parameter
	 * cannot be matched and it isn't explicitly marked with @{@link Nullable} a
	 * {@link LyciaParsingException} is thrown. Default behaviour is backward
	 * compatible and defaults to false.
	 * 
	 * @param nullAware
	 *            If this parser instance should allow null parameters or not
	 * @since 1.9.9
	 */
	void setNullAware(boolean nullAware);

	/**
	 * Returns if the parameter matcher should work in an null aware way. For
	 * more description see methods setNullAware
	 * 
	 * @return If this parser instance should allow null parameters or not
	 * @since 1.9.9
	 */
	boolean isNullAware();

	/**
	 * Adds a new {@link EndTagAware} to the list
	 * 
	 * @param listener
	 *            The listener to add to the list
	 * @since 1.9.9
	 */
	void addEndTagReachedListener(EndTagAware<B> listener);

	/**
	 * Removes a {@link EndTagAware} from the list
	 * 
	 * @param listener
	 *            The listener to remove from the list
	 * @since 1.9.9
	 */
	void removeEndTagReachedListener(EndTagAware<B> listener);

	/**
	 * Returns the unmodifiable list of {@link EndTagAware} previously
	 * registered
	 * 
	 * @return An unmodifiable list of EndTagReachedListener
	 * @since 1.9.9
	 */
	List<EndTagAware<B>> getEndTagReachedListeners();

	/**
	 * Returns if this {@link LyciaParser} is ignoring comments. Default
	 * behavior is true.
	 * 
	 * @return If is ignoring comments
	 * @since 1.9.9
	 */
	boolean isIgnoringComments();

	/**
	 * Sets if this {@link LyciaParser} is ignoring comments.
	 * 
	 * @param ignore
	 *            Lycia should ignore comments
	 * @since 1.9.9
	 */
	void setIgnoringComments(boolean ignore);

	/**
	 * Adds a globally registered {@link TypeConverter} to this
	 * {@link LyciaConfigurator} instance
	 * 
	 * @param typeConverter
	 *            TypeConverter instance to register
	 * @since 1.9.9
	 */
	void addGlobalDataConverter(TypeConverter typeConverter);

	/**
	 * Removes a previously globally registered {@link TypeConverter} from this
	 * {@link LyciaConfigurator} instance
	 * 
	 * 
	 * @param typeConverter
	 *            TypeConverter instance to remove
	 * @since 1.9.9
	 */
	void removeGlobalDataConverter(TypeConverter typeConverter);

	/**
	 * Returns all globally registered {@link TypeConverter}s
	 * 
	 * @return A list of registered TypeConverters
	 * @since 1.9.9
	 */
	List<TypeConverter> getTypeConverters();

}
